package com.fauks.restful.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.UUID;

public class GenTempOssUtil {

    private static final String ENCODING = "UTF-8";

    private static final String STANDARD_DATE_FORMAT_UTC = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";

    private final static Logger log = LoggerFactory.getLogger(GenTempOssUtil.class);

    public static void main(String[] args) throws Exception {
    /*    String accessId = "LTAI4FsYgJxxJAsNq8ismffR";
        String secretKey = "SbQQqAlgNyc4EToylEJchH86JCKX3w";   */

        String accessId = "LTAIdsBRiKN0US3v";
        String secretKey = "udTlOjLDsSnlwJfg2p9B4dIshx1ul3";
        String arn = "acs:ram::1345980603198608:role/aliyunsasbaselinerole";
        genOssInfo(accessId, secretKey, arn);
    }


    /**
     * @param @param accessId 子账户的accessId
     * @param @param secretKey 子账户的secretKey
     * @param @param arn       对应子账户的权限信息等
     * @Title: genOssInfo
     * @Description: 生产临时的 oss 信息
     */
    public static String genOssInfo(String accessId, String secretKey, String arn) {
        StringBuilder stringToSign = new StringBuilder();
        StringBuilder canonicalizedQueryString = new StringBuilder();
        StringBuilder reqBuilder = new StringBuilder();
        String resp = null;
        String uuid = UUID.randomUUID().toString();

        SimpleDateFormat sdf = new SimpleDateFormat(STANDARD_DATE_FORMAT_UTC);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        String timestamp = sdf.format(new Date());

        stringToSign.append("GET&%2F&");

        try {
            canonicalizedQueryString.append("AccessKeyId=" + URLEncoder.encode(accessId, ENCODING))
                    .append("&Action=" + URLEncoder.encode("AssumeRole", ENCODING))
                    .append("&Format=" + URLEncoder.encode("JSON", ENCODING))
                    .append("&GET=")
                    .append("&RoleArn=" + URLEncoder.encode(arn, ENCODING))
                    .append("&RoleSessionName=" + URLEncoder.encode("client", ENCODING))
                    .append("&SignatureMethod=" + URLEncoder.encode("HMAC-SHA1", ENCODING))
                    .append("&SignatureNonce=" + URLEncoder.encode(uuid, ENCODING))
                    .append("&SignatureVersion=" + URLEncoder.encode("1.0", ENCODING))
                    .append("&Timestamp=" + URLEncoder.encode(timestamp, ENCODING))
                    .append("&Version=" + URLEncoder.encode("2015-04-01", ENCODING));

            stringToSign.append(URLEncoder.encode(canonicalizedQueryString.toString(), ENCODING));

            log.info("加签字符串:" + stringToSign.toString());
            String genHMAC = genHMAC(stringToSign.toString(), secretKey + "&");

            reqBuilder.append("Format=" + URLEncoder.encode("JSON", ENCODING))
                    .append("&Version=" + URLEncoder.encode("2015-04-01", ENCODING))
                    .append("&AccessKeyId=" + URLEncoder.encode(accessId, ENCODING))
                    .append("&Signature=" + URLEncoder.encode(genHMAC, ENCODING))
                    .append("&SignatureMethod=" + URLEncoder.encode("HMAC-SHA1", ENCODING))
                    .append("&SignatureVersion=" + URLEncoder.encode("1.0", ENCODING))
                    .append("&SignatureNonce=" + URLEncoder.encode(uuid, ENCODING))
                    .append("&Timestamp=" + URLEncoder.encode(timestamp, ENCODING))
                    .append("&Action=" + URLEncoder.encode("AssumeRole", ENCODING))
                    .append("&GET=")
                    .append("&RoleArn=" + URLEncoder.encode(arn, ENCODING))
                    .append("&RoleSessionName=" + URLEncoder.encode("client", ENCODING));
        } catch (UnsupportedEncodingException e1) {
            resp = "{\"msg\":\"获取oss信息参数编码转换异常\"}";
            log.error("获取oss信息参数编码转换异常", e1);
        }

        try {
            String reqUrl = "https://sts.aliyuncs.com/?" + reqBuilder.toString();
            log.info("请求 获取临时的 oss 信息 地址：" + reqUrl);
            resp = HttpClientUtil.getRequest(reqUrl);
            JSONObject obj = JSON.parseObject(resp);
            obj.put("msg", "success");
            obj.put("desc", "success");
            resp = JSON.toJSONString(obj);
            log.info("阿里云返回的 oss 结果信息 ：" + resp);
        } catch (Exception e) {
            JSONObject obj = new JSONObject();
            obj.put("msg", "failed");
            obj.put("desc", "获取临时的oss信息异常");
            resp = JSON.toJSONString(obj);
            log.error("获取临时的oss信息异常", e);
        }
        return resp;
    }


    /**
     * 使用 HMAC-SHA1 签名方法对data进行签名
     *
     * @param data 被签名的字符串
     * @param key  密钥
     * @return 加密后的字符串
     */
    public static String genHMAC(String data, String key) {
        byte[] result = null;
        try {
            //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称    
            SecretKeySpec signinKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
            //生成一个指定 Mac 算法 的 Mac 对象    
            Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
            //用给定密钥初始化 Mac 对象    
            mac.init(signinKey);
            //完成 Mac 操作     
            byte[] rawHmac = mac.doFinal(data.getBytes());
            result = Base64.encodeBase64(rawHmac);

        } catch (Exception e) {
            log.error("HMAC-SHA1 加密失败", e);
        }
        if (null != result) {
            return new String(result);
        } else {
            return null;
        }
    }
}